package com.xuyiwei.mayi.service;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.AlipaySignature;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.xuyiwei.mayi.alipay.config.AlipayConfig;
import com.xuyiwei.mayi.base.BaseApiService;
import com.xuyiwei.mayi.base.ResponseBase;
import com.xuyiwei.mayi.constants.Constants;
import com.xuyiwei.mayi.entity.PaymentInfo;
import com.xuyiwei.mayi.feign.OrderServiceFeign;
import com.xuyiwei.mayi.mapper.PaymentInfoDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.Map;

/**
 * Created by xuyiwei on 2019/5/5.
 */
@RestController
@Slf4j
public class PayCallBackServiceImpl extends BaseApiService implements PayCallBackService{

    @Autowired
    private PaymentInfoDao paymentInfoDao;

    @Autowired
    private OrderServiceFeign orderServiceFeign;

    @Override
    public ResponseBase synCallBack(@RequestParam Map<String, String> params) {
        log.info("####同步回调开始####params:",params);
        try {
            //调用SDK验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
            //——请在这里编写您的程序（以下代码仅作参考）——
            if(signVerified) {
                //商户订单号
                String out_trade_no = new String(params.get("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

                //支付宝交易号
                String trade_no = new String(params.get("trade_no").getBytes("ISO-8859-1"),"UTF-8");

                //付款金额
                String total_amount = new String(params.get("total_amount").getBytes("ISO-8859-1"),"UTF-8");


                //同步跳转会使用GET请求，URL后面会自带一大串数字，因此可以使用form表单提交方式规避掉
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("trade_no",trade_no);
                jsonObject.put("out_trade_no",out_trade_no);
                jsonObject.put("total_amount",total_amount);
                return setResultSuccess(jsonObject);
            }else {
                return setResultError("验签失败");
            }
        } catch (Exception e) {
            return setResultError("支付宝同步回调出现异常");
        }


    }

    @Override
    @LcnTransaction //分布式事务注解
    //事务回滚最好加上rollbackFor不然不起作用
    @Transactional(rollbackFor = Exception.class)
    public String asynCallBack(@RequestParam Map<String, String> params) throws Exception {

        try{

            log.info("进入支付服务的重试机制");
            boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名

            //——请在这里编写您的程序（以下代码仅作参考）——

            /* 实际验证过程建议商户务必添加以下校验：
            1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
            2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
            3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
            4、验证app_id是否为该商户本身。
            */
            if(signVerified) {//验证成功
                //商户订单号
                String out_trade_no =  params.get("out_trade_no") ;

                //支付宝交易号
                String trade_no =  params.get("trade_no" );

                //交易状态
                String trade_status = params.get("trade_status" );

                if(trade_status.equals("TRADE_FINISHED")){
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //如果有做过处理，不执行商户的业务程序

                    //注意：
                    //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                }else if (trade_status.equals("TRADE_SUCCESS")){
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //如果有做过处理，不执行商户的业务程序

                    //注意：
                    //付款完成后，支付宝系统发送该交易状态通知
                    PaymentInfo paymentInfo = paymentInfoDao.getByOrderIdPayInfo(out_trade_no);
                    if(paymentInfo==null){
                        return Constants.ALIBABA_ERROR;
                    }
                    Integer state = paymentInfo.getState()==null?0:paymentInfo.getState();
                    if (state.equals("1")) {
                        return Constants.ALIBABA_PASS;
                    }

                    paymentInfo.setPlatformorderId(trade_no);
                    paymentInfo.setState(1);
                    paymentInfo.setPayMessage("支付宝支付");
                    paymentInfo.setUpdated(new Date());


                    //更改订单信息
                    // 手动 begin begin
                    Integer updateResult = paymentInfoDao.updatePayInfo(paymentInfo);
                    if (updateResult <= 0) {
                        return Constants.ALIBABA_ERROR;
                    }
                    // 调用订单接口通知 支付状态
                    ResponseBase orderResult = orderServiceFeign.updateOrderIdInfo(1l, trade_no, out_trade_no);
                    if (!orderResult.getCode().equals(Constants.HTTP_RES_CODE_200)) {
                        // 回滚 手动回滚 rollback
                        return Constants.ALIBABA_ERROR;
                    }
                    //这里涉及分布式事务的问题 如果这里抛出的异常  远程rpc调用是不会回滚的 这就里需要一个监控中心去
                    int z = 1/0;

                    // 2PC 3PC TCC MQ
                    // 手动 提交 comiit;
                    return Constants.ALIBABA_PASS;

                }

                return Constants.ALIBABA_ERROR;

            }else {//验证失败
                return Constants.ALIBABA_ERROR;

                //调试用，写文本函数记录程序运行情况是否正常
                //String sWord = AlipaySignature.getSignCheckContentV1(params);
                //AlipayConfig.logResult(sWord);
            }


        }catch (Exception e){
            throw new Exception("抛出异常");
        }
    }
}
